package com.andy.eqm.server.socket;



import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.andy.eqm.server.action.IReqAction;
import com.andy.eqm.server.distruptor.base.BaseEvent;
import com.andy.eqm.server.distruptor.base.MessageProducer;
import com.andy.eqm.server.game.Global;
import com.andy.eqm.server.socket.codec.DataWrap;
import com.andy.eqm.server.utils.CommonUtils;
import com.andy.eqm.server.utils.SpringContextHolder;
import com.google.common.collect.Maps;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.AttributeKey;
import io.netty.util.ReferenceCountUtil;

public class SocketFrameHandler extends SimpleChannelInboundHandler<ByteBuf>{
	
	private Logger logger = LoggerFactory.getLogger(getClass());
	
	public static AttributeKey<NettySocketSession> nssKey = AttributeKey.valueOf("netty.channel.session.key");
	
	private Map<Integer,IReqAction> actions = Maps.newHashMap();
	
	private boolean isInDis = false;
	
	private MessageProducer producer;
	
	public SocketFrameHandler(boolean autoRelease) {
		super(autoRelease);
	}

	@Override
	public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
		super.channelRegistered(ctx);
		// 初始化session
		NettySocketSession session = new NettySocketSession(ctx);
		ctx.channel().attr(nssKey).getAndSet(session);
		
		isInDis = getProducer() != null;
	}
	
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		Global.addSession(ctx.channel().attr(nssKey).get());
		super.channelActive(ctx);
	}
	
	@Override
	protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
		NettySocketSession session = ctx.channel().attr(nssKey).get();
		if(session == null) {
			ReferenceCountUtil.release(msg);
			return ;
		}
		int action = msg.readInt();
		if(logger.isInfoEnabled()){
			logger.info("来自客户端消息:{}", action);
		}
		
		if(isInDis){
			doInDisruptor(session, action, new DataWrap(msg));
		}else{
			if(session.getUser() == null){
				logger.error("用户没有登录，请确认");
			}
			IReqAction webAction = actions.get(action);
			if(webAction == null){
				webAction = SpringContextHolder.getBean(GmAction.ACTION_PREFIX+action, IReqAction.class);
				actions.putIfAbsent(action, webAction);
			}
			try {
				webAction.doAction(session,new DataWrap(msg));
			} catch (Exception e) {
				logger.error("执行逻辑异常", e);
			} finally {
				if(msg.refCnt() > 0) {
					ReferenceCountUtil.safeRelease(msg);
				}
			}
		}
		
	}
	
	void doInDisruptor(NettySocketSession session,int action,DataWrap dataWrap){
		getProducer().publish(new BaseEvent(session,action,dataWrap));
	}
	
	public MessageProducer getProducer(){
		if(producer == null){
			producer = SpringContextHolder.getBean(MessageProducer.class);
		}
		return producer;
	}
	
	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		NettySocketSession session = ctx.channel().attr(nssKey).get();
		// 先退出房间
		CommonUtils.outRoom(session.getUser(),2);
		Global.removeSession(session);
	}
	
	@Override
	public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
		logger.info("Current channel handlerRemoved");
	}
	
	
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		logger.error("连接异常", cause);
	}
}